home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / graphics / gnuplot / gnuplot-3.7.1src / gnuplot-3.7.1 / readline.c < prev    next >
C/C++ Source or Header  |  1999-11-29  |  28KB  |  1,106 lines

  1. #ifndef lintnot DOS386 */
  2. }
  3. Sid = "$Id: readline.c,v 1.9.2.1 1999/08/19 14:38:07 lhecking Exp $";
  4. #endif
  5.  
  6. /* GNUPLOT - readline.c */
  7.  
  8. /*[
  9.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  10.  *
  11.  * Permission to use, copy, and distribute this software and its
  12.  * documentation for any purpose with or without fee is hereby granted,
  13.  * provided that the above copyright notice appear in all copies and
  14.  * that both that copyright notice and this permission notice appear
  15.  * in supporting documentation.
  16.  *
  17.  * Permission to modify the software is granted, but not the right to
  18.  * distribute the complete modified source code.  Modifications are to
  19.  * be distributed as patches to the released version.  Permission to
  20.  * distribute binaries produced by compiling modified sources is granted,
  21.  * provided you
  22.  *   1. distribute the corresponding source modifications from the
  23.  *    released version in the form of a patch file along with the binaries,
  24.  *   2. add special version identification to distinguish your version
  25.  *    in addition to the base release version number,
  26.  *   3. provide your name and address as the primary contact for the
  27.  *    support of your modified version, and
  28.  *   4. retain our contact information in regard to use of the base
  29.  *    software.
  30.  * Permission to distribute the released version of the source code along
  31.  * with corresponding source modifications in the form of a patch file is
  32.  * granted with same provisions 2 through 4 for binary distributions.
  33.  *
  34.  * This software is provided "as is" without express or implied warranty
  35.  * to the extent permitted by applicable law.
  36. ]*/
  37.  
  38.  
  39. /* 
  40.  * AUTHORS
  41.  *
  42.  *   Original Software:
  43.  *     Tom Tkacik
  44.  *
  45.  *   Msdos port and some enhancements:
  46.  *     Gershon Elber and many others.
  47.  *
  48.  *   In add_history(), do not store duplicated entries:
  49.  *     Petr Mikulik
  50.  */
  51.  
  52. #include <signal.h>
  53. /* get prototype for alloc and gpfaralloc */
  54. #include "plot.h"
  55.  
  56. #if defined(READLINE) && !defined(HAVE_LIBREADLINE)
  57.  
  58. /* a small portable version of GNU's readline
  59.  * this is not the BASH or GNU EMACS version of READLINE due to Copyleft 
  60.  * restrictions
  61.  * do not need any terminal capabilities except backspace,
  62.  * and space overwrites a character
  63.  */
  64.  
  65. /* NANO-EMACS line editing facility
  66.  * printable characters print as themselves (insert not overwrite)
  67.  * ^A moves to the beginning of the line
  68.  * ^B moves back a single character
  69.  * ^E moves to the end of the line
  70.  * ^F moves forward a single character
  71.  * ^K kills from current position to the end of line
  72.  * ^P moves back through history
  73.  * ^N moves forward through history
  74.  * ^H and DEL delete the previous character
  75.  * ^D deletes the current character, or EOF if line is empty
  76.  * ^L/^R redraw line in case it gets trashed
  77.  * ^U kills the entire line
  78.  * ^W kills last word
  79.  * LF and CR return the entire line regardless of the cursor postition
  80.  * EOF with an empty line returns (char *)NULL
  81.  *
  82.  * all other characters are ignored
  83.  */
  84.  
  85. #ifdef __linux__
  86. /* HBB: to get prototype for ioctl() */
  87. # include <sys/ioctl.h>
  88. #endif
  89.  
  90. /* replaces the previous klugde in configure */
  91. #if defined(HAVE_TERMIOS_H) && defined(HAVE_TCGETATTR)
  92. # define TERMIOS
  93. #else /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
  94. # ifdef HAVE_SGTTY_H
  95. #  define SGTTY
  96. # endif
  97. #endif /* not HAVE_TERMIOS_H && HAVE_TCGETATTR */
  98.  
  99. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386) && !defined(OSK)
  100.  
  101. /*
  102.  * Set up structures using the proper include file
  103.  */
  104. # if defined(_IBMR2) || defined(alliant)
  105. #  define SGTTY
  106. # endif
  107.  
  108. /*  submitted by Francois.Dagorn@cicb.fr */
  109. # ifdef SGTTY
  110. #  include <sgtty.h>
  111. static struct sgttyb orig_termio, rl_termio;
  112. /* define terminal control characters */
  113. static struct tchars s_tchars;
  114. #  ifndef VERASE
  115. #   define VERASE    0
  116. #  endif            /* not VERASE */
  117. #  ifndef VEOF
  118. #   define VEOF      1
  119. #  endif            /* not VEOF */
  120. #  ifndef VKILL
  121. #   define VKILL     2
  122. #  endif            /* not VKILL */
  123. #  ifdef TIOCGLTC        /* available only with the 'new' line discipline */
  124. static struct ltchars s_ltchars;
  125. #   ifndef VWERASE
  126. #    define VWERASE   3
  127. #   endif            /* not VWERASE */
  128. #   ifndef VREPRINT
  129. #    define VREPRINT  4
  130. #   endif            /* not VREPRINT */
  131. #   ifndef VSUSP
  132. #    define VSUSP     5
  133. #   endif            /* not VSUP */
  134. #  endif            /* TIOCGLTC */
  135. #  ifndef NCCS
  136. #   define NCCS      6
  137. #  endif            /* not NCCS */
  138.  
  139. # else                /* not SGTTY */
  140.  
  141. /* SIGTSTP defines job control
  142.  * if there is job control then we need termios.h instead of termio.h
  143.  * (Are there any systems with job control that use termio.h?  I hope not.)
  144.  */
  145. #  if defined(SIGTSTP) || defined(TERMIOS)
  146. #   ifndef TERMIOS
  147. #    define TERMIOS
  148. #   endif            /* not TERMIOS */
  149. #   include <termios.h>
  150. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  151. #   ifdef ISC22
  152. #    ifndef ONOCR        /* taken from sys/termio.h */
  153. #     define ONOCR 0000020    /* true at least for ISC 2.2 */
  154. #    endif            /* not ONOCR */
  155. #    ifndef IUCLC
  156. #     define IUCLC 0001000
  157. #    endif            /* not IUCLC */
  158. #   endif            /* ISC22 */
  159. #   if !defined(IUCLC)
  160.      /* translate upper to lower case not supported */
  161. #    define IUCLC 0
  162. #   endif            /* not IUCLC */
  163.  
  164. static struct termios orig_termio, rl_termio;
  165. #  else                /* not SIGSTP || TERMIOS */
  166. #   include <termio.h>
  167. static struct termio orig_termio, rl_termio;
  168. /* termio defines NCC instead of NCCS */
  169. #   define NCCS    NCC
  170. #  endif            /* not SIGTSTP || TERMIOS */
  171. # endif                /* SGTTY */
  172.  
  173. /* ULTRIX defines VRPRNT instead of VREPRINT */
  174. # if defined(VRPRNT) && !defined(VREPRINT)
  175. #  define VREPRINT VRPRNT
  176. # endif                /* VRPRNT */
  177.  
  178. /* define characters to use with our input character handler */
  179. static char term_chars[NCCS];
  180.  
  181. static int term_set = 0;    /* =1 if rl_termio set */
  182.  
  183. #define special_getc() ansi_getc()
  184. static int ansi_getc __PROTO((void));
  185.  
  186. #else /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
  187.  
  188. # ifdef _Windows
  189. #  include <windows.h>
  190. #  include "win/wtext.h"
  191. #  include "win/wgnuplib.h"
  192. extern TW textwin;
  193. #  define TEXTUSER 0xf1
  194. #  define TEXTGNUPLOT 0xf0
  195. #  define special_getc() msdos_getch()
  196. static char msdos_getch __PROTO((void));    /* HBB 980308: PROTO'ed it */
  197. # endif                /* _Windows */
  198.  
  199. # if defined(MSDOS) || defined(DOS386)
  200. /* MSDOS specific stuff */
  201. #  ifdef DJGPP
  202. #   include <pc.h>
  203. #  endif            /* DJGPP */
  204. #  ifdef __EMX__
  205. #   include <conio.h>
  206. #  endif            /* __EMX__ */
  207. #  define special_getc() msdos_getch()
  208. static char msdos_getch();
  209. # endif                /* MSDOS || DOS386 */
  210.  
  211. # ifdef OSK
  212. #  include <sgstat.h>
  213. #  include <modes.h>
  214.  
  215. #  define STDIN    0
  216. static int term_set = 0;    /* =1 if new_settings is set */
  217.  
  218. static struct _sgs old_settings;    /* old terminal settings        */
  219. static struct _sgs new_settings;    /* new terminal settings        */
  220.  
  221. #  define special_getc() ansi_getc()
  222. static int ansi_getc __PROTO((void));
  223.  
  224. /* On OS9 a '\n' is a character 13 and '\r' == '\n'. This gives troubles
  225.    here, so we need a new putc wich handles this correctly and print a
  226.    character 10 on each place we want a '\n'.
  227.  */
  228. #  undef putc            /* Undefine the macro for putc */
  229.  
  230. static int putc(c, fp)
  231. char c;
  232. FILE *fp;
  233. {
  234.     write(fileno(fp), &c, 1);
  235.     if (c == '\012') {        /* A normal ASCII '\n' */
  236.     c = '\r';
  237.     write(fileno(fp), &c, 1);
  238.     }
  239. }
  240.  
  241. # endif                /* OSK */
  242.  
  243. # if defined(ATARI) || defined(MTOS)
  244. #  define special_getc() tos_getch()
  245. # endif                /* ATARI || MTOS */
  246.  
  247. #endif /* MSDOS or ATARI or MTOS or _Windows or DOS386 or OSK */
  248.  
  249. #ifdef OS2
  250. # if defined( special_getc )
  251. #  undef special_getc()
  252. # endif                /* special_getc */
  253. # define special_getc() msdos_getch()
  254. static char msdos_getch __PROTO((void));    /* HBB 980308: PROTO'ed it */
  255. #endif /* OS2 */
  256.  
  257.  
  258. /* initial size and increment of input line length */
  259. #define MAXBUF    1024
  260. /* ^H */
  261. #define BACKSPACE 0x08
  262. #define SPACE    ' '
  263.  
  264. #ifdef OSK
  265. # define NEWLINE    '\012'
  266. #else /* OSK */
  267. # define NEWLINE    '\n'
  268. #endif /* not OSK */
  269.  
  270. struct hist {
  271.     char *line;
  272.     struct hist *prev;
  273.     struct hist *next;
  274. };
  275.  
  276. static struct hist *history = NULL;    /* no history yet */
  277. static struct hist *cur_entry = NULL;
  278.  
  279. static char *cur_line;        /* current contents of the line */
  280. static int line_len = 0;
  281. static int cur_pos = 0;        /* current position of the cursor */
  282. static int max_pos = 0;        /* maximum character position */
  283.  
  284.  
  285. static void fix_line __PROTO((void));
  286. static void redraw_line __PROTO((char *prompt));
  287. static void clear_line __PROTO((char *prompt));
  288. static void clear_eoline __PROTO((void));
  289. static void copy_line __PROTO((char *line));
  290. static void set_termio __PROTO((void));
  291. static void reset_termio __PROTO((void));
  292. static int ansi_getc __PROTO((void));
  293. static int user_putc __PROTO((int ch));
  294. static int user_puts __PROTO((char *str));
  295. static void backspace __PROTO((void));
  296. static void extend_cur_line __PROTO((void));
  297.  
  298. /* user_putc and user_puts should be used in the place of
  299.  * fputc(ch,stderr) and fputs(str,stderr) for all output
  300.  * of user typed characters.  This allows MS-Windows to 
  301.  * display user input in a different color.
  302.  */
  303. static int user_putc(ch)
  304. int ch;
  305. {
  306.     int rv;
  307. #ifdef _Windows
  308.     TextAttr(&textwin, TEXTUSER);
  309. #endif
  310.     rv = fputc(ch, stderr);
  311. #ifdef _Windows
  312.     TextAttr(&textwin, TEXTGNUPLOT);
  313. #endif
  314.     return rv;
  315. }
  316.  
  317. static int user_puts(str)
  318. char *str;
  319. {
  320.     int rv;
  321. #ifdef _Windows
  322.     TextAttr(&textwin, TEXTUSER);
  323. #endif
  324.     rv = fputs(str, stderr);
  325. #ifdef _Windows
  326.     TextAttr(&textwin, TEXTGNUPLOT);
  327. #endif
  328.     return rv;
  329. }
  330.  
  331. /* This function provides a centralized non-destructive backspace capability
  332.  * M. Castro
  333.  */
  334. static void backspace()
  335. {
  336.     user_putc(BACKSPACE);
  337. }
  338.  
  339. static void extend_cur_line()
  340. {
  341.     char *new_line;
  342.  
  343.     /* extent input line length */
  344.     new_line = gp_realloc(cur_line, line_len + MAXBUF, NULL);
  345.     if (!new_line) {
  346.     reset_termio();
  347.     int_error("Can't extend readline length", NO_CARET);
  348.     }
  349.     cur_line = new_line;
  350.     line_len += MAXBUF;
  351.     FPRINTF((stderr, "\nextending readline length to %d chars\n", line_len));
  352. }
  353.  
  354. char *
  355.  readline(prompt)
  356. char *prompt;
  357. {
  358.  
  359.     int cur_char;
  360.     char *new_line;
  361.  
  362.     /* start with a string of MAXBUF chars */
  363.  
  364.     if (line_len != 0) {
  365.     free(cur_line);
  366.     line_len = 0;
  367.     }
  368.     cur_line = gp_alloc((unsigned long) MAXBUF, "readline");
  369.     line_len = MAXBUF;
  370.  
  371.     /* set the termio so we can do our own input processing */
  372.     set_termio();
  373.  
  374.     /* print the prompt */
  375.     fputs(prompt, stderr);
  376.     cur_line[0] = '\0';
  377.     cur_pos = 0;
  378.     max_pos = 0;
  379.     cur_entry = NULL;
  380.  
  381.     /* get characters */
  382.     for (;;) {
  383.     cur_char = special_getc();
  384.  
  385. /*
  386.  * The #define CHARSET7BIT should be used when one encounters problems with
  387.  * 8bit characters that should not be entered on the commandline. I cannot
  388.  * think on any reasonable example where this could happen, but what do I know?
  389.  * After all, the unix world still ignores 8bit chars in most applications.
  390.  *
  391.  * Note that latin1 defines the chars 0x80-0x9f as control chars. For the
  392.  * benefit of Atari, MSDOS, Windows and NeXT I have decided to ignore this,
  393.  * since it would require more #ifs.
  394.  *
  395.  */
  396.  
  397. #ifdef CHARSET7BIT
  398.     if (isprint(cur_char)) {
  399. #else /* CHARSET7BIT */
  400.     if (isprint(cur_char) || (((unsigned char) cur_char > 0x7f) &&
  401.                   cur_char != EOF)) {
  402. #endif /* CHARSET7BIT */
  403.         int i;
  404.  
  405.         if (max_pos + 1 >= line_len) {
  406.         extend_cur_line();
  407.         }
  408.         for (i = max_pos; i > cur_pos; i--) {
  409.         cur_line[i] = cur_line[i - 1];
  410.         }
  411.         user_putc(cur_char);
  412.         cur_line[cur_pos] = cur_char;
  413.         cur_pos += 1;
  414.         max_pos += 1;
  415.         if (cur_pos < max_pos)
  416.         fix_line();
  417.         cur_line[max_pos] = '\0';
  418.  
  419.         /* else interpret unix terminal driver characters */
  420. #ifdef VERASE
  421.     } else if (cur_char == term_chars[VERASE]) {    /* DEL? */
  422.         if (cur_pos > 0) {
  423.         int i;
  424.         cur_pos -= 1;
  425.         backspace();
  426.         for (i = cur_pos; i < max_pos; i++)
  427.             cur_line[i] = cur_line[i + 1];
  428.         max_pos -= 1;
  429.         fix_line();
  430.         }
  431. #endif /* VERASE */
  432. #ifdef VEOF
  433.     } else if (cur_char == term_chars[VEOF]) {    /* ^D? */
  434.         if (max_pos == 0) {
  435.         reset_termio();
  436.         return ((char *) NULL);
  437.         }
  438.         if ((cur_pos < max_pos) && (cur_char == 004)) {    /* ^D */
  439.         int i;
  440.         for (i = cur_pos; i < max_pos; i++)
  441.             cur_line[i] = cur_line[i + 1];
  442.         max_pos -= 1;
  443.         fix_line();
  444.         }
  445. #endif /* VEOF */
  446. #ifdef VKILL
  447.     } else if (cur_char == term_chars[VKILL]) {    /* ^U? */
  448.         clear_line(prompt);
  449. #endif /* VKILL */
  450. #ifdef VWERASE
  451.     } else if (cur_char == term_chars[VWERASE]) {    /* ^W? */
  452.         while ((cur_pos > 0) &&
  453.            (cur_line[cur_pos - 1] == SPACE)) {
  454.         cur_pos -= 1;
  455.         backspace();
  456.         }
  457.         while ((cur_pos > 0) &&
  458.            (cur_line[cur_pos - 1] != SPACE)) {
  459.         cur_pos -= 1;
  460.         backspace();
  461.         }
  462.         clear_eoline();
  463.         max_pos = cur_pos;
  464. #endif /* VWERASE */
  465. #ifdef VREPRINT
  466.     } else if (cur_char == term_chars[VREPRINT]) {    /* ^R? */
  467.         putc(NEWLINE, stderr);    /* go to a fresh line */
  468.         redraw_line(prompt);
  469. #endif /* VREPRINT */
  470. #ifdef VSUSP
  471.     } else if (cur_char == term_chars[VSUSP]) {
  472.         reset_termio();
  473.         kill(0, SIGTSTP);
  474.  
  475.         /* process stops here */
  476.  
  477.         set_termio();
  478.         /* print the prompt */
  479.         redraw_line(prompt);
  480. #endif /* VSUSP */
  481.     } else {
  482.         /* do normal editing commands */
  483.         /* some of these are also done above */
  484.         int i;
  485.         switch (cur_char) {
  486.         case EOF:
  487.         reset_termio();
  488.         return ((char *) NULL);
  489.         case 001:        /* ^A */
  490.         while (cur_pos > 0) {
  491.             cur_pos -= 1;
  492.             backspace();
  493.         }
  494.         break;
  495.         case 002:        /* ^B */
  496.         if (cur_pos > 0) {
  497.             cur_pos -= 1;
  498.             backspace();
  499.         }
  500.         break;
  501.         case 005:        /* ^E */
  502.         while (cur_pos < max_pos) {
  503.             user_putc(cur_line[cur_pos]);
  504.             cur_pos += 1;
  505.         }
  506.         break;
  507.         case 006:        /* ^F */
  508.         if (cur_pos < max_pos) {
  509.             user_putc(cur_line[cur_pos]);
  510.             cur_pos += 1;
  511.         }
  512.         break;
  513.         case 013:        /* ^K */
  514.         clear_eoline();
  515.         max_pos = cur_pos;
  516.         break;
  517.         case 020:        /* ^P */
  518.         if (history != NULL) {
  519.             if (cur_entry == NULL) {
  520.             cur_entry = history;
  521.             clear_line(prompt);
  522.             copy_line(cur_entry->line);
  523.             } else if (cur_entry->prev != NULL) {
  524.             cur_entry = cur_entry->prev;
  525.             clear_line(prompt);
  526.             copy_line(cur_entry->line);
  527.             }
  528.         }
  529.         break;
  530.         case 016:        /* ^N */
  531.         if (cur_entry != NULL) {
  532.             cur_entry = cur_entry->next;
  533.             clear_line(prompt);
  534.             if (cur_entry != NULL)
  535.             copy_line(cur_entry->line);
  536.             else
  537.             cur_pos = max_pos = 0;
  538.         }
  539.         break;
  540.         case 014:        /* ^L */
  541.         case 022:        /* ^R */
  542.         putc(NEWLINE, stderr);    /* go to a fresh line */
  543.         redraw_line(prompt);
  544.         break;
  545.         case 0177:        /* DEL */
  546.         case 010:        /* ^H */
  547.         if (cur_pos > 0) {
  548.             cur_pos -= 1;
  549.             backspace();
  550.             for (i = cur_pos; i < max_pos; i++)
  551.             cur_line[i] = cur_line[i + 1];
  552.             max_pos -= 1;
  553.             fix_line();
  554.         }
  555.         break;
  556.         case 004:        /* ^D */
  557.         if (max_pos == 0) {
  558.             reset_termio();
  559.             return ((char *) NULL);
  560.         }
  561.         if (cur_pos < max_pos) {
  562.             for (i = cur_pos; i < max_pos; i++)
  563.             cur_line[i] = cur_line[i + 1];
  564.             max_pos -= 1;
  565.             fix_line();
  566.         }
  567.         break;
  568.         case 025:        /* ^U */
  569.         clear_line(prompt);
  570.         break;
  571.         case 027:        /* ^W */
  572.         while ((cur_pos > 0) &&
  573.                (cur_line[cur_pos - 1] == SPACE)) {
  574.             cur_pos -= 1;
  575.             backspace();
  576.         }
  577.         while ((cur_pos > 0) &&
  578.                (cur_line[cur_pos - 1] != SPACE)) {
  579.             cur_pos -= 1;
  580.             backspace();
  581.         }
  582.         clear_eoline();
  583.         max_pos = cur_pos;
  584.         break;
  585.         case '\n':        /* ^J */
  586. #ifndef OSK
  587.         case '\r':        /* ^M */
  588. #endif
  589.         cur_line[max_pos + 1] = '\0';
  590. #ifdef OS2
  591.         while (cur_pos < max_pos) {
  592.             user_putc(cur_line[cur_pos]);
  593.             cur_pos += 1;
  594.         }
  595. #endif
  596.         putc(NEWLINE, stderr);
  597.  
  598.         /* Shrink the block down to fit the string ?
  599.          * if the alloc fails, we still own block at cur_line,
  600.          * but this shouldn't really fail.
  601.          */
  602.         new_line = (char *) gp_realloc(cur_line, (unsigned long) (strlen(cur_line) + 1), "line resize");
  603.         if (new_line)
  604.             cur_line = new_line;
  605.         /* else we just hang on to what we had - it's not a problem */
  606.  
  607.         line_len = 0;
  608.         FPRINTF((stderr, "Resizing input line to %d chars\n", strlen(cur_line)));
  609.         reset_termio();
  610.         return (cur_line);
  611.         default:
  612.         break;
  613.         }
  614.     }
  615.     }
  616. }
  617.  
  618. /* fix up the line from cur_pos to max_pos
  619.  * do not need any terminal capabilities except backspace,
  620.  * and space overwrites a character
  621.  */
  622. static void fix_line()
  623. {
  624.     int i;
  625.  
  626.     /* write tail of string */
  627.     for (i = cur_pos; i < max_pos; i++)
  628.     user_putc(cur_line[i]);
  629.  
  630.     /* write a space at the end of the line in case we deleted one */
  631.     user_putc(SPACE);
  632.  
  633.     /* backup to original position */
  634.     for (i = max_pos + 1; i > cur_pos; i--)
  635.     backspace();
  636.  
  637. }
  638.  
  639. /* redraw the entire line, putting the cursor where it belongs */
  640. static void redraw_line(prompt)
  641. char *prompt;
  642. {
  643.     int i;
  644.  
  645.     fputs(prompt, stderr);
  646.     user_puts(cur_line);
  647.  
  648.     /* put the cursor where it belongs */
  649.     for (i = max_pos; i > cur_pos; i--)
  650.     backspace();
  651. }
  652.  
  653. /* clear cur_line and the screen line */
  654. static void clear_line(prompt)
  655. char *prompt;
  656. {
  657.     int i;
  658.     for (i = 0; i < max_pos; i++)
  659.     cur_line[i] = '\0';
  660.  
  661.     for (i = cur_pos; i > 0; i--)
  662.     backspace();
  663.  
  664.     for (i = 0; i < max_pos; i++)
  665.     putc(SPACE, stderr);
  666.  
  667.     putc('\r', stderr);
  668.     fputs(prompt, stderr);
  669.  
  670.     cur_pos = 0;
  671.     max_pos = 0;
  672. }
  673.  
  674. /* clear to end of line and the screen end of line */
  675. static void clear_eoline()
  676. {
  677.     int i;
  678.     for (i = cur_pos; i < max_pos; i++)
  679.     cur_line[i] = '\0';
  680.  
  681.     for (i = cur_pos; i < max_pos; i++)
  682.     putc(SPACE, stderr);
  683.     for (i = cur_pos; i < max_pos; i++)
  684.     backspace();
  685. }
  686.  
  687. /* copy line to cur_line, draw it and set cur_pos and max_pos */
  688. static void copy_line(line)
  689. char *line;
  690. {
  691.     while (strlen(line) + 1 > line_len) {
  692.     extend_cur_line();
  693.     }
  694.     strcpy(cur_line, line);
  695.     user_puts(cur_line);
  696.     cur_pos = max_pos = strlen(cur_line);
  697. }
  698.  
  699. /* add line to the history */
  700. void add_history(line)
  701. char *line;
  702. {
  703.     struct hist *entry;
  704.  
  705.     entry = history;
  706.     while (entry != NULL) {
  707.     /* Don't store duplicate entries */
  708.     if (!strcmp(entry->line, line)) {
  709.         /* cmd lines are equal, relink entry that was found last */
  710.         if (entry->next == NULL) {
  711.         /* previous command repeated, no change */
  712.         return;
  713.         }
  714.         if (entry->prev == NULL) {
  715.         /* current cmd line equals the first in the history */
  716.         (entry->next)->prev = NULL;
  717.         history->next = entry;
  718.         entry->prev = history;
  719.         entry->next = NULL;
  720.         history = entry;
  721.         return;
  722.         }
  723.         /* bridge over entry's vacancy, then move it to the end */
  724.         (entry->prev)->next = entry->next;
  725.         (entry->next)->prev = entry->prev;
  726.         entry->prev = history;
  727.         history->next = entry;
  728.         entry->next = NULL;
  729.         history = entry;
  730.         return;
  731.     }
  732.     entry = entry->prev;
  733.     }                /* end of not-storing duplicated entries */
  734.  
  735.     entry = (struct hist *) gp_alloc((unsigned long) sizeof(struct hist), "history");
  736.     entry->line = gp_alloc((unsigned long) (strlen(line) + 1), "history");
  737.     strcpy(entry->line, line);
  738.  
  739.     entry->prev = history;
  740.     entry->next = NULL;
  741.     if (history != NULL) {
  742.     history->next = entry;
  743.     }
  744.     history = entry;
  745. }
  746.  
  747.  
  748. /* Convert ANSI arrow keys to control characters */
  749. static int ansi_getc()
  750. {
  751.     int c = getc(stdin);
  752.     if (c == 033) {
  753.     c = getc(stdin);    /* check for CSI */
  754.     if (c == '[') {
  755.         c = getc(stdin);    /* get command character */
  756.         switch (c) {
  757.         case 'D':        /* left arrow key */
  758.         c = 002;
  759.         break;
  760.         case 'C':        /* right arrow key */
  761.         c = 006;
  762.         break;
  763.         case 'A':        /* up arrow key */
  764.         c = 020;
  765.         break;
  766.         case 'B':        /* down arrow key */
  767.         c = 016;
  768.         break;
  769.         }
  770.     }
  771.     }
  772.     return c;
  773. }
  774.  
  775. #if defined(MSDOS) || defined(_Windows) || defined(DOS386) || defined(OS2)
  776.  
  777. /* Convert Arrow keystrokes to Control characters: */
  778. static char msdos_getch()
  779. {
  780. #ifdef DJGPP
  781.     char c;
  782.     int ch = getkey();
  783.     c = (ch & 0xff00) ? 0 : ch & 0xff;
  784. #else /* not DJGPP */
  785. # ifdef OS2
  786.     char c = getc(stdin);
  787. # else                /* not OS2 */
  788.     char c = getch();
  789. # endif                /* not OS2 */
  790. #endif /* not DJGPP */
  791.  
  792.     if (c == 0) {
  793. #ifdef DJGPP
  794.     c = ch & 0xff;
  795. #else /* not DJGPP */
  796. # ifdef OS2
  797.     c = getc(stdin);
  798. # else                /* not OS2 */
  799.     c = getch();        /* Get the extended code. */
  800. # endif                /* not OS2 */
  801. #endif /* not DJGPP */
  802.     switch (c) {
  803.     case 75:        /* Left Arrow. */
  804.         c = 002;
  805.         break;
  806.     case 77:        /* Right Arrow. */
  807.         c = 006;
  808.         break;
  809.     case 72:        /* Up Arrow. */
  810.         c = 020;
  811.         break;
  812.     case 80:        /* Down Arrow. */
  813.         c = 016;
  814.         break;
  815.     case 115:        /* Ctl Left Arrow. */
  816.     case 71:        /* Home */
  817.         c = 001;
  818.         break;
  819.     case 116:        /* Ctl Right Arrow. */
  820.     case 79:        /* End */
  821.         c = 005;
  822.         break;
  823.     case 83:        /* Delete */
  824.         c = 004;
  825.         break;
  826.     default:
  827.         c = 0;
  828.         break;
  829.     }
  830.     } else if (c == 033) {    /* ESC */
  831.     c = 025;
  832.     }
  833.     return c;
  834. }
  835.  
  836. #endif /* MSDOS || _Windows || DOS386 || OS2 */
  837.  
  838.  
  839. #if defined(ATARI) || defined(MTOS)
  840.  
  841. /* Convert Arrow keystrokes to Control characters: TOS version */
  842.  
  843. long poll_events(int);        /* from term/atariaes.trm */
  844.  
  845. /* this function is used in help.c as well. this means that the
  846.  * program doesn't work without -DREADLINE (which would be the case
  847.  * if help.c didn't use it as well, since no events would be processed)
  848.  */
  849. char tos_getch()
  850. {
  851.     long rawkey;
  852.     char c;
  853.     int scan_code;
  854.     static int in_help = 0;
  855.  
  856.     if (strcmp(term->name, "atari") == 0)
  857.     poll_events(0);
  858.  
  859.     if (in_help) {
  860.     switch (in_help) {
  861.     case 1:
  862.     case 5:
  863.         in_help++;
  864.         return 'e';
  865.     case 2:
  866.     case 6:
  867.         in_help++;
  868.         return 'l';
  869.     case 3:
  870.     case 7:
  871.         in_help++;
  872.         return 'p';
  873.     case 4:
  874.         in_help = 0;
  875.         return 0x0d;
  876.     case 8:
  877.         in_help = 0;
  878.         return ' ';
  879.     }
  880.     }
  881.     if (strcmp(term->name, "atari") == 0) {
  882.     do {
  883.         if (Bconstat(2))
  884.         rawkey = Cnecin();
  885.         else
  886.         rawkey = poll_events(1);
  887.     } while (rawkey == 0);
  888.     } else
  889.     rawkey = Cnecin();
  890.  
  891.     c = (char) rawkey;
  892.     scan_code = ((int) (rawkey >> 16)) & 0xff;    /* get the scancode */
  893.     if (Kbshift(-1) & 0x00000007)
  894.     scan_code |= 0x80;    /* shift or control ? */
  895.  
  896.     switch (scan_code) {
  897.     case 0x62:            /* HELP         */
  898.     case 0xe2:            /* shift HELP   */
  899.     if (max_pos == 0) {
  900.         if (scan_code == 0x62) {
  901.         in_help = 1;
  902.         } else {
  903.         in_help = 5;
  904.         }
  905.         return 'h';
  906.     } else {
  907.         return 0;
  908.     }
  909.     case 0x48:            /* Up Arrow */
  910.     return 0x10;        /* ^P */
  911.     case 0x50:            /* Down Arrow */
  912.     return 0x0e;        /* ^N */
  913.     case 0x4b:            /* Left Arrow */
  914.     return 0x02;        /* ^B */
  915.     case 0x4d:            /* Right Arrow */
  916.     return 0x06;        /* ^F */
  917.     case 0xcb:            /* Shift Left Arrow */
  918.     case 0xf3:            /* Ctrl Left Arrow (TOS-bug ?) */
  919.     case 0x47:            /* Home */
  920.     return 0x01;        /* ^A */
  921.     case 0xcd:            /* Shift Right Arrow */
  922.     case 0xf4:            /* Ctrl Right Arrow (TOS-bug ?) */
  923.     case 0xc7:            /* Shift Home */
  924.     case 0xf7:            /* Ctrl Home */
  925.     return 0x05;        /* ^E */
  926.     case 0x61:            /* Undo - redraw line */
  927.     return 0x0c;        /* ^L */
  928.     default:
  929.     if (c == 0x1b)
  930.         return 0x15;    /* ESC becomes ^U */
  931.     if (c == 0x7f)
  932.         return 0x04;    /* Del becomes ^D */
  933.     break;
  934.     }
  935.     return c;
  936. }
  937.  
  938. #endif /* ATARI || MTOS */
  939.  
  940.   /* set termio so we can do our own input processing */
  941. static void set_termio()
  942. {
  943. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
  944. /* set termio so we can do our own input processing */
  945. /* and save the old terminal modes so we can reset them later */
  946.     if (term_set == 0) {
  947.     /*
  948.      * Get terminal modes.
  949.      */
  950. # ifndef OSK
  951. #  ifdef SGTTY
  952.     ioctl(0, TIOCGETP, &orig_termio);
  953. #  else                /* not SGTTY */
  954. #   ifdef TERMIOS
  955. #    ifdef TCGETS
  956.     ioctl(0, TCGETS, &orig_termio);
  957. #    else            /* not TCGETS */
  958.     tcgetattr(0, &orig_termio);
  959. #    endif            /* not TCGETS */
  960. #   else            /* not TERMIOS */
  961.     ioctl(0, TCGETA, &orig_termio);
  962. #   endif            /* TERMIOS */
  963. #  endif            /* not SGTTY */
  964. # else                /* OSK */
  965.     setbuf(stdin, (char *) 0);    /* Make stdin and stdout unbuffered */
  966.     setbuf(stderr, (char *) 0);
  967.     _gs_opt(STDIN, &new_settings);
  968. # endif                /* OSK */
  969.  
  970.     /*
  971.      * Save terminal modes
  972.      */
  973. # ifndef OSK
  974.     rl_termio = orig_termio;
  975. # else                /* OSK */
  976.     _gs_opt(STDIN, &old_settings);
  977. # endif                /* OSK */
  978.  
  979.     /*
  980.      * Set the modes to the way we want them
  981.      *  and save our input special characters
  982.      */
  983. # ifndef OSK
  984. #  ifdef SGTTY
  985.     rl_termio.sg_flags |= CBREAK;
  986.     rl_termio.sg_flags &= ~(ECHO | XTABS);
  987.     ioctl(0, TIOCSETN, &rl_termio);
  988.  
  989.     ioctl(0, TIOCGETC, &s_tchars);
  990.     term_chars[VERASE] = orig_termio.sg_erase;
  991.     term_chars[VEOF] = s_tchars.t_eofc;
  992.     term_chars[VKILL] = orig_termio.sg_kill;
  993. #   ifdef TIOCGLTC
  994.     ioctl(0, TIOCGLTC, &s_ltchars);
  995.     term_chars[VWERASE] = s_ltchars.t_werasc;
  996.     term_chars[VREPRINT] = s_ltchars.t_rprntc;
  997.     term_chars[VSUSP] = s_ltchars.t_suspc;
  998.  
  999.     /* disable suspending process on ^Z */
  1000.     s_ltchars.t_suspc = 0;
  1001.     ioctl(0, TIOCSLTC, &s_ltchars);
  1002. #   endif            /* TIOCGLTC */
  1003. #  else                /* not SGTTY */
  1004.     rl_termio.c_iflag &= ~(BRKINT | PARMRK | INPCK | IUCLC | IXON | IXOFF);
  1005.     rl_termio.c_iflag |= (IGNBRK | IGNPAR);
  1006.  
  1007.     /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
  1008.  
  1009.     rl_termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH);
  1010. #   ifdef OS2
  1011.     /* for emx: remove default terminal processing */
  1012.     rl_termio.c_lflag &= ~(IDEFAULT);
  1013. #   endif            /* OS2 */
  1014.     rl_termio.c_lflag |= (ISIG);
  1015.     rl_termio.c_cc[VMIN] = 1;
  1016.     rl_termio.c_cc[VTIME] = 0;
  1017.  
  1018. #   ifndef VWERASE
  1019. #    define VWERASE 3
  1020. #   endif            /* VWERASE */
  1021.     term_chars[VERASE] = orig_termio.c_cc[VERASE];
  1022.     term_chars[VEOF] = orig_termio.c_cc[VEOF];
  1023.     term_chars[VKILL] = orig_termio.c_cc[VKILL];
  1024. #   ifdef TERMIOS
  1025.     term_chars[VWERASE] = orig_termio.c_cc[VWERASE];
  1026. #    ifdef VREPRINT
  1027.     term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
  1028. #    else            /* not VREPRINT */
  1029. #     ifdef VRPRNT
  1030.     term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
  1031. #     endif            /* VRPRNT */
  1032. #    endif            /* not VREPRINT */
  1033.     term_chars[VSUSP] = orig_termio.c_cc[VSUSP];
  1034.  
  1035.     /* disable suspending process on ^Z */
  1036.     rl_termio.c_cc[VSUSP] = 0;
  1037. #   endif            /* TERMIOS */
  1038. #  endif            /* not SGTTY */
  1039. # else                /* OSK */
  1040.     new_settings._sgs_echo = 0;    /* switch off terminal echo */
  1041.     new_settings._sgs_pause = 0;    /* inhibit page pause */
  1042.     new_settings._sgs_eofch = 0;    /* inhibit eof  */
  1043.     new_settings._sgs_kbich = 0;    /* inhibit ^C   */
  1044.     new_settings._sgs_kbach = 0;    /* inhibit ^E   */
  1045. # endif                /* OSK */
  1046.  
  1047.     /*
  1048.      * Set the new terminal modes.
  1049.      */
  1050. # ifndef OSK
  1051. #  ifdef SGTTY
  1052.     ioctl(0, TIOCSLTC, &s_ltchars);
  1053. #  else                /* not SGTTY */
  1054. #   ifdef TERMIOS
  1055. #    ifdef TCSETSW
  1056.     ioctl(0, TCSETSW, &rl_termio);
  1057. #    else            /* not TCSETSW */
  1058.     tcsetattr(0, TCSADRAIN, &rl_termio);
  1059. #    endif            /* not TCSETSW */
  1060. #   else            /* not TERMIOS */
  1061.     ioctl(0, TCSETAW, &rl_termio);
  1062. #   endif            /* not TERMIOS */
  1063. #  endif            /* not SGTTY */
  1064. # else                /* OSK */
  1065.     _ss_opt(STDIN, &new_settings);
  1066. # endif                /* OSK */
  1067.     term_set = 1;
  1068.     }
  1069. #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
  1070. }
  1071.  
  1072. static void reset_termio()
  1073. {
  1074. #if !defined(MSDOS) && !defined(ATARI) && !defined(MTOS) && !defined(_Windows) && !defined(DOS386)
  1075. /* reset saved terminal modes */
  1076.     if (term_set == 1) {
  1077. # ifndef OSK
  1078. #  ifdef SGTTY
  1079.     ioctl(0, TIOCSETN, &orig_termio);
  1080. #   ifdef TIOCGLTC
  1081.     /* enable suspending process on ^Z */
  1082.     s_ltchars.t_suspc = term_chars[VSUSP];
  1083.     ioctl(0, TIOCSLTC, &s_ltchars);
  1084. #   endif            /* TIOCGLTC */
  1085. #  else                /* not SGTTY */
  1086. #   ifdef TERMIOS
  1087. #    ifdef TCSETSW
  1088.     ioctl(0, TCSETSW, &orig_termio);
  1089. #    else            /* not TCSETSW */
  1090.     tcsetattr(0, TCSADRAIN, &orig_termio);
  1091. #    endif            /* not TCSETSW */
  1092. #   else            /* not TERMIOS */
  1093.     ioctl(0, TCSETAW, &orig_termio);
  1094. #   endif            /* TERMIOS */
  1095. #  endif            /* not SGTTY */
  1096. # else                /* OSK */
  1097.     _ss_opt(STDIN, &old_settings);
  1098. # endif                /* OSK */
  1099.     term_set = 0;
  1100.     }
  1101. #endif /* not MSDOS && not ATARI && not MTOS && not _Windows && not DOS386 */
  1102. }
  1103.  
  1104.  
  1105. #endif /* READLINE && not HAVE_LIBREADLINE */
  1106.